package cn.zhf.shop.utils;

import cn.zhf.shop.config.GlobalConfig;
import cn.zhf.shop.entity.*;
import cn.zhf.shop.mapper.AccountDealMapper;
import cn.zhf.shop.mapper.AccountDealTitleMapper;
import cn.zhf.shop.mapper.AuditTitleMapper;
import cn.zhf.shop.mapper.FinancialMapper;
import cn.zhf.shop.service.AccountDealService;
import cn.zhf.shop.service.AuditService;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

@Component
public class ChinaPayUtil {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private AccountDealService accountDealService;
    @Autowired
    private AuditService auditService;
    @Autowired
    private GlobalConfig config;
    @Autowired
    private FinancialMapper financialMapper;
    @Autowired
    private AccountDealTitleMapper accountDealTitleMapper;
    @Autowired
    private AuditTitleMapper auditTitleMapper;


    private static ChinaPayUtil instance;

    @PostConstruct
    public void init() {
        instance = this;
    }


    public static String test_ChinaPay_url = "https://newpayment-test.chinapay.com/CTITS/service/rest/page/nref/000000000017/0/0/0/0/0";            //测试中国银联支付接口

    public static  String test_front_ChinaPay_url = "https://newpayment-test.chinapay.com/CTITS/service/rest/page/nref/000000000017/0/0/0/0/0";

    public static String ChinaPay_url = "https://payment.chinapay.com/CTITS/service/rest/forward/syn/000000000017/0/0/0/0/0";                      //正式_前台模式_中国银联支付接口

    public static String Refund_test_url = "https://newpayment-test.chinapay.com/CTITS/service/rest/forward/syn/000000000065/0/0/0/0/0";           //测试退款中国银联支付接口

    public static String Refund_url = "https://payment.chinapay.com/CTITS/service/rest/forward/syn/000000000065/0/0/0/0/0";                         //正式退款中国银联支付接口

    public static String Refund_Back_url = "https://qiudaokeji.cn/shop/api/pay/chinapayrefund";                         //正式退款中国银联支付接口

    public static final String PACKET = "packet";

    public static final String RESULT_MAP = "resultMap";

    public static String Version = "20150922";                                                                                                     //版本号

    public static String MerId = "737572009040001";                                                                                                //商户号

    public static String MerPageUrl = "https://qiudaokeji.cn/zhihuifu/#/";                                      //用来接收交易结果的前台跳转页面的地址，用于引导付款人支付后返回商户网站页面


    public static String MerBgUrl = "https://qiudaokeji.cn/shop/api/pay/chinapayback";                                                   //用来接收交易结果后台通知的地址

    public static String accountDealPath = "financial/accountDeal/";

    public static String auditPath = "financial/audit/";


    // AN8..40 商户订单号，不能含"-"或"_"
    public static String getOrderId() {
        return new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
    }


    public static String getTime() {
        return new SimpleDateFormat("yyyy-MM-dd_").format(new Date());
    }

    // 商户发送交易时间 格式:yyyyMMddHHmmss
    public static String getCurrentTime() {
        return new SimpleDateFormat("yyyyMMdd").format(new Date());
    }

    // 商户发送交易时间 格式:HHmmss
    public static String getTranTime() {
        return new SimpleDateFormat("HHMMss").format(new Date());
    }


//    //检测返回值的错误
//    public static boolean verify(Map map) {
//        SecssUtil secssUtil = new SecssUtil();
//        secssUtil.init();
//        secssUtil.verify(map);
//        if (!"00".equals(secssUtil.getErrCode())) {
//            instance.logger.warn(" 验 签 过 程 发 生 错 误 ， 错 误 信 息 为 -->"+secssUtil.getErrMsg());
//            return false;
//        }
//        instance.logger.warn("验签通过");
//        return true;
//    }

    /**
     * hashMap 转化成表单字符串
     *
     * @return
     */

    //表单字符串转换成HashMap
    public static HashMap<String, String> StrToMap(String formData) {
        String[] params;
        HashMap<String, String> map = new HashMap<String, String>();

        //params按照&将每个键值对分割成字符串数组
        params = formData.split("&");

        //增强for遍历
        for (String s : params) {
            String[] list = s.split("=");
            if (list.length > 1) {
                map.put(list[0], list[1]);
            }
        }
        return map;
    }

    //hashMap转换成表单字符串
    public static String mapToForm(Map<String,Object> map){
        //StringBuilder和StringBuffer可以把任意类型数据放进字符串缓存区里面，并换回字符串缓冲区本身
        StringBuilder stringBuilder = new StringBuilder();

        if(map==null){
            return stringBuilder.toString();
        }else{
            //增强for遍历hashMap
            //Set<Map.Entry<String,String>> 键值对对象集合
            for(Map.Entry<String,Object> entry : map.entrySet()){
                stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            return stringBuilder.substring(0,stringBuilder.length()-1);
        }
    }

    //返回当天日期减一天
    public static String subDate(){
        Calendar calendar= Calendar.getInstance();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd_");
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
        return dateFormat.format(calendar.getTime());
    }



    public static  List<File> files = new ArrayList<File>();

    /**
     * 解压文件
     *
     * @param filePath       压缩文件路径
     */
    public static boolean unzip(String filePath,int type) {
        File source = new File(filePath);                                                //拿到路径得压缩文件
        if (source.exists()) {                                                           //资源存在则继续
            ZipInputStream zis = null;                                                   //压缩文件得输入流
            BufferedOutputStream bos = null;                                             //字节缓冲输出流
            try {
                zis = new ZipInputStream(new FileInputStream(source));                   //拿到整个得压缩文件得输入流
                ZipEntry entry = null;                                                   //压缩文件内部文件对象
                while ((entry = zis.getNextEntry()) != null
                        && !entry.isDirectory()) {                                       //判断是否还有下一个压缩文件内部文件对象
                    File target = new File(source.getParent(), entry.getName());         //判断是否还有下一个压缩文件内部文件对象
                    if (!target.getParentFile().exists()) {                              //判断文件的目录是否存在,不存在则创建
                        // 创建文件父目录
                        target.getParentFile().mkdirs();
                    }
                    // 写入文件
                    bos = new BufferedOutputStream(new FileOutputStream(target));        //读取文件,拿到输出流
                    int read = 0;
                    byte[] buffer = new byte[1024 * 10];                                 // 创建缓存数组
                    while ((read = zis.read(buffer, 0, buffer.length)) != -1) {
                        bos.write(buffer, 0, read);                                  // 将buffer数据 写入到文件当中
                    }
                    bos.flush();                                                         //强制把数据清空
                    return fileHandle(target,entry.getName(),type);                      //把生成文件传输到下一个步骤处理
                }
                zis.closeEntry();                                                       //关闭压缩文件输入流
            } catch (IOException e) {
                throw new RuntimeException(e);
            } finally {
                closeQuietly(zis, bos);                                                 //关闭IO数据流

            }
        }
        return false;
    }

    /**
     * 关闭一个或多个流对象
     *
     * @param closeables
     *            可关闭的流对象列表
     * @throws IOException
     */
    public static void close(Closeable... closeables) throws IOException {
        if (closeables != null) {
            for (Closeable closeable : closeables) {
                if (closeable != null) {
                    closeable.close();
                }
            }
        }
    }

    /**
     * 关闭一个或多个流对象
     *
     * @param closeables
     *            可关闭的流对象列表
     */
    public static void closeQuietly(Closeable... closeables) {
        try {
            close(closeables);
        } catch (IOException e) {
            // do nothing
        }
    }


    /**
     * 完成文件的读取
     * @param fileName    文件路径
     */
    private static boolean fileHandle(File file,String fileName,int type){
        List<String> contentLine = new ArrayList<>();
        List<AccountDeal> accountDealList = new ArrayList<>();
        BufferedReader bufferedreader = null;
        FileReader fr = null;
        try{
            fr = new FileReader(file);
            bufferedreader = new BufferedReader(fr);
            String line = null;
            while(true){
                line = bufferedreader.readLine();
                if(line == null){
                    break;
                }
                contentLine.add(line);
                files.add(file);
            }
            return dataHandle(contentLine,fileName,type);
        }catch(Exception e){
            instance.logger.warn("IO处理出现异常: "+e);
        }finally{
            try{
                bufferedreader.close();
                fr.close();
            }catch(Exception e){
                instance.logger.warn("IO处理出现异常: "+e);
            }
        }
        return false;
    }

    /**
     * 完成文件数据的处理
     * @param contentLine    所有的行数据
     */
    private static boolean dataHandle(List<String> contentLine,String fileName,int type) throws CloneNotSupportedException, ParseException {
        String[] newLine = null;
        if(type == 1){
            List<AccountDeal> accountDealList = new ArrayList<>();
            String[] line = contentLine.get(0).split("\\|");
            //创建SimpleDateFormat对象实例并定义好转换格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            AccountDealTitle accountDealTitle = new AccountDealTitle();
            accountDealTitle.setVersion(line[0]);
            accountDealTitle.setCountpay(line[1]);
            accountDealTitle.setCountpayamt(line[2]);
            accountDealTitle.setCountpaysuc(line[3]);
            accountDealTitle.setCountpaysucamt(line[4]);
            accountDealTitle.setCountpaycancel(line[5]);
            accountDealTitle.setCountpaycancelamt(line[6]);
            accountDealTitle.setCountpaycancelsuc(line[7]);
            accountDealTitle.setCountpaycancelamtsuc(line[8]);
            accountDealTitle.setCountrefundsuc(line[9]);
            accountDealTitle.setCountrefundamtsuc(line[10]);
            accountDealTitle.setCountrefundcancel(line[11]);
            accountDealTitle.setCountrefundcancelamt(line[12]);
            accountDealTitle.setCountrefundcancelsuc(line[13]);
            accountDealTitle.setCountrefundcancelamtsuc(line[14]);
            Date date = sdf.parse(ChinaPayUtil.subDate());
            accountDealTitle.setUpdateTime(date);
            instance.accountDealTitleMapper.insertSelective(accountDealTitle);
            int id = instance.accountDealTitleMapper.selectByUpdateTime(sdf.format(date)).get(0).getAccountDealTitleId();
            AccountDeal target1 = new AccountDeal();
            for(int i=1;i<contentLine.size()-1;i++){
                AccountDeal accountDeal= (AccountDeal) target1.clone();
                newLine = contentLine.get(i).split("\\|");
                accountDeal.setTrandate(newLine[0].equals("")==true?null:newLine[0]);
                accountDeal.setAcqcode(newLine[1].equals("")==true?null:newLine[1]);
                accountDeal.setMerid(newLine[2].equals("")==true?null:newLine[2]);
                accountDeal.setTranreserved(newLine[3].equals("")==true?null:newLine[3]);
                accountDeal.setLiqdate(newLine[4].equals("")==true?null:newLine[4]);
                accountDeal.setMerorderno(newLine[5].equals("")==true?null:newLine[5]);
                accountDeal.setBankinstno(newLine[6].equals("")==true?null:newLine[6]);
                accountDeal.setCurryno(newLine[7].equals("")==true?null:newLine[7]);
                accountDeal.setTrantype(newLine[8].equals("")==true?null:newLine[8]);
                accountDeal.setBusitype(newLine[9].equals("")==true?null:newLine[9]);
                accountDeal.setOrderstatus(newLine[10].equals("")==true?null:newLine[10]);
                accountDeal.setChannelrespcode(newLine[11].equals("")==true?null:newLine[11]);
                accountDeal.setCompletedate(newLine[12].equals("")==true?null:newLine[12]);
                accountDeal.setCompletetime(newLine[13].equals("")==true?null:newLine[13]);
                accountDeal.setOrderamt(BigDecimal.valueOf(Integer.parseInt(newLine[14].equals("")==true?"0":newLine[14])));
                accountDeal.setAcqseqid(newLine[15].equals("")==true?null:newLine[15]);
                accountDeal.setAcqdate(newLine[16].equals("")==true?null:newLine[16]);
                accountDeal.setAcqtime(newLine[17].equals("")==true?null:newLine[17]);
                accountDeal.setOritrandate(newLine[18].equals("")==true?null:newLine[18]);
                accountDeal.setOriorderno(newLine[19].equals("")==true?null:newLine[19]);
                accountDeal.setDcmark(newLine[20].equals("")==true?null:newLine[20]);
                accountDeal.setMerresv(newLine[21].equals("")==true?null:newLine[21]);
                accountDeal.setSplittype(newLine[22].equals("")==true?null:newLine[22]);
                accountDeal.setSplitmethod(newLine[23].equals("")==true?null:newLine[23]);
                accountDeal.setMersplitmsg(newLine[24].equals("")==true?null:newLine[24]);
                accountDeal.setCommoditymsg(newLine[25].equals("")==true?null:newLine[25]);
                accountDeal.setPaybillno(newLine[26].equals("")==true?null:newLine[26]);
                accountDeal.setTerm(newLine[27].equals("")==true?null:newLine[27]);
                accountDeal.setReviewdate(newLine[28].equals("")==true?null:newLine[28]);
                accountDeal.setTermianlid(newLine[29].equals("")==true?null:newLine[29]);
                accountDeal.setAccountAccountDealTitleId(id);
                accountDealList.add(accountDeal);
            }
            //对加载完的数据 进行添加
            if(accountDealList.size()==0){
                instance.logger.info(sdf.format(new Date())+" 今日接收的交易对账数据为空");
            }else{
                instance.accountDealService.batchInsertSelective(accountDealList);
            }
                return true;
        }

        if(type==2){
            List<Audit> auditList = new ArrayList<>();
            Audit target2 = new Audit();
            String[] line = contentLine.get(0).split("\\|");
            //创建SimpleDateFormat对象实例并定义好转换格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            AuditTitle auditTitle = new AuditTitle();
            auditTitle.setVersion(line[0].equals("")==true?null:line[0]);
            auditTitle.setLiqdate(line[1].equals("")==true?null:line[1]);
            auditTitle.setSharecnt(line[2].equals("")==true?null:line[2]);
            auditTitle.setShareamt(line[3].equals("")==true?null:line[3]);
            auditTitle.setFeeamt(line[4].equals("")==true?null:line[4]);
            auditTitle.setSharerefcnt(line[5].equals("")==true?null:line[5]);
            auditTitle.setSharerefamt(line[6].equals("")==true?null:line[6]);
            auditTitle.setLiqamt(line[7].equals("")==true?null:line[7]);
            Date date = sdf.parse(ChinaPayUtil.subDate());
            auditTitle.setUpdateTime(date);
           instance.auditTitleMapper.insertSelective(auditTitle);
           int id = instance.auditTitleMapper.selectByUpdateTime(sdf.format(date)).get(0).getAuditTitleId();
            for(int i=1;i<contentLine.size()-1;i++){
                Audit audit= (Audit) target2.clone();
                newLine = contentLine.get(i).split("\\|");
                audit.setTrandate(newLine[0].equals("")==true?null:newLine[0]);
                audit.setAcqcode(newLine[1].equals("")==true?null:newLine[1]);
                audit.setShareshopid(newLine[2].equals("")==true?null:newLine[2]);
                audit.setShopid(newLine[3].equals("")==true?null:newLine[3]);
                audit.setLiqdate(newLine[4].equals("")==true?null:newLine[4]);
                audit.setMerorderno(newLine[5].equals("")==true?null:newLine[5]);
                audit.setBankno(newLine[6].equals("")==true?null:newLine[6]);
                audit.setCurryno(newLine[7].equals("")==true?null:newLine[7]);
                audit.setTrantype(newLine[8].equals("")==true?null:newLine[8]);
                audit.setOrderstatus(newLine[9].equals("")==true?null:newLine[9]);
                audit.setCompletedate(newLine[10].equals("")==true?null:newLine[10]);
                audit.setCompletetime(newLine[11].equals("")==true?null:newLine[11]);
                audit.setSharetradeamt(BigDecimal.valueOf(Integer.parseInt(newLine[12].equals("")==true?"0":newLine[12])));
                audit.setSharefeeamt(BigDecimal.valueOf(Integer.parseInt(newLine[13].equals("")==true?"0":newLine[13])));
                audit.setLiqamt(BigDecimal.valueOf(Integer.parseInt(newLine[14].equals("")==true?"0":newLine[14])));
                audit.setDcmark(newLine[15].equals("")==true?null:newLine[15]);
                audit.setMerresv(newLine[16].equals("")==true?null:newLine[16]);
                audit.setAcqdate(newLine[17].equals("")==true?null:newLine[17]);
                audit.setAcqtime(newLine[18].equals("")==true?null:newLine[18]);
                audit.setAcqseqid(newLine[19].equals("")==true?null:newLine[19]);
                audit.setOritrandate(newLine[20].equals("")==true?null:newLine[20]);
                audit.setOriorderno(newLine[21].equals("")==true?null:newLine[21]);
                audit.setReportreserved(newLine[22].equals("")==true?null:newLine[22]);
                audit.setResv1(newLine[23].equals("")==true?null:newLine[23]);
                audit.setResv2(newLine[24].equals("")==true?null:newLine[24]);
                audit.setResv3(newLine[25].equals("")==true?null:newLine[25]);
                audit.setResv4(newLine[26].equals("")==true?null:newLine[26]);
                audit.setAuditAuditTitleId(id);
                auditList.add(audit);
            }
            //对加载完的数据 进行添加
            if(auditList.size()==0){
                instance.logger.info(sdf.format(new Date())+" 今日接收的清算对账数据为空");
            }else{
                instance.auditService.batchInsertSelective(auditList);
            }
            return true;
        }
        return false;
    }


    public static void deleteFile() throws IOException {
        if(files.size()!=0){
            for(File target : files){
                FileUtils.deleteQuietly(target);
            }
            files.clear();
        }else{
            files.clear();
            instance.logger.info("清理解压文件........");
        }

    }


    public static synchronized boolean Financial(Financial financial,String filename,String type,String download) throws IOException {

        List<Financial> financials =instance.financialMapper.selectAllByDownloadAndType(financial.getDownload(),type);
        if(financials.size()==0) {
            if("1".equals(type)) {
                boolean isDownload = DownloadUtil.downLoadFromUrl(download,filename,instance.config.globalFilePath+accountDealPath,1);
                if(isDownload) {
                    instance.financialMapper.insertSelective(financial);
                    boolean isSuccess=ChinaPayUtil.unzip(instance.config.globalFilePath + accountDealPath + File.separator + filename, 1);
                    instance.logger.info("处理对账文件数据情况(true:成功,false:失败): "+isSuccess);
                    return  isSuccess;
                }else {
                    instance.logger.warn("下载失败  444");
                    return  false;
                }
            }else if("2".equals(type)) {
                boolean isDownload = DownloadUtil.downLoadFromUrl(download,filename,instance.config.globalFilePath+auditPath,2);
                if(isDownload) {
                    instance.financialMapper.insertSelective(financial);
                    boolean isSuccess=ChinaPayUtil.unzip(instance.config.globalFilePath + auditPath + File.separator + filename, 2);
                    instance.logger.info("处理对账文件数据情况(true:成功,false:失败): "+isSuccess);
                    return  isSuccess;
                }else {
                    instance.logger.warn("下载失败 455");
                    return  false;
                }
            }
        }
            return  false;
        }
    }



